home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 25 / Cream of the Crop 25.iso / compress / tar321__.zip / SOURCES.ZIP / READOPT.C < prev    next >
C/C++ Source or Header  |  1997-03-31  |  16KB  |  505 lines

  1. #include "modern.h"
  2. #ifdef MODERN
  3. #    include <stdlib.h>
  4. #    include <string.h>
  5. #    ifdef ZMEM
  6. #        define MEMCPY(d,s,n) strcpy(d,s)
  7. #    endif
  8. #    ifdef NOMEMCPY
  9. #        define MEMCPY(d,s,n) strcpy(d,s)
  10. #    endif
  11. #    ifndef MEMCPY
  12. #        define MEMCPY(d,s,n) memcpy(d,s,n)
  13. #    endif
  14. #    ifdef __TURBOC__
  15. #        include <io.h>
  16. #    endif
  17. #else
  18. #    define MEMCPY(d,s,n) strcpy(d,s)
  19.     char *strcpy(), *getenv(), *malloc(), *realloc();
  20.         int strlen();
  21. #endif
  22. #include <stdio.h>
  23. #include "define.h"
  24. #include "lzwbits.h"
  25.  
  26. #ifdef MSDOS
  27. #    define switchar(c) ((c)=='-' || (c)=='/')
  28. #else
  29. #    define switchar(c) ((c)=='/')
  30. #endif
  31.  
  32. void revector(argc, argv, n)
  33. char ***argv;
  34. {
  35.    register i;
  36.  
  37.    /* create new argument vector */
  38.    i = (int)((argc + n) * sizeof(char *));
  39.    if (argvector) {
  40.       free(argvector);
  41.       if ((argvector=(char**)realloc(argvector, i)) == NULL) outmem(stderr);
  42.    } else {
  43.       argvector = (char **)salloc(i);
  44.       /* copy origin arguments */
  45.       for (i=0; i<argc; i++) argvector[i] = (*argv)[i];
  46.    }
  47.    *argv = argvector;
  48. }
  49.  
  50. int buildarg(argc, argv, buf)
  51. char ***argv, *buf;
  52. {
  53.    register c;
  54.    register i, n;
  55.  
  56.    i = 0; n = 0;
  57.    while (buf[i]) { /* count number of words in responce file */
  58.       while ((c=buf[i])!='\0' && space(c)) ++i;
  59.       if (buf[i]) ++n; /* next word found */
  60.       while ((c=buf[i])!='\0' && !space(c)) ++i;
  61.    }
  62.    revector(argc, argv, n);
  63.    i = argc; n = 0;
  64.    while (buf[n]) {/* append new arguments */
  65.       while ((c=buf[n])!='\0' && space(c)) buf[n++] = '\0';
  66.       if (buf[n]) argvector[i++] = buf+n; /* next word found */
  67.       while ((c=buf[n])!='\0' && !space(c)) ++n;
  68.    }
  69.    return i;
  70. }
  71.  
  72. #define INDMAX 32760
  73. #define INDMIN 1024
  74. #define INDLOW 1023
  75.  
  76. int argfile(argc, argv, fname, buf)
  77. char ***argv, *fname, **buf;
  78. {
  79.    register i;
  80.    register l = 0;
  81.    register char *p = NULL;
  82.  
  83.    if (fname[0] == '-' && fname[1] == '\0') {
  84.       /* standard input */ i = 0;
  85.    } else if ((i = open(fname, OM_RDONLY)) < 0 || fstat(i, &st) < 0) {
  86.       (void)fprintf(stderr, "Tar: can\'t process \'%s\'\n", fname);
  87.       done(ERRARG);
  88.    }
  89.    if ((st.st_mode & S_IFMT) == S_IFREG) {
  90.       if (st.st_size >= INDMAX) {
  91.          (void)fprintf(stderr, "Tar: \'%s\' exceeds limit in size\n", fname);
  92.          done(ERRARG);
  93.       }
  94.       p = salloc((l = (int)st.st_size) + 1);
  95. /* Note: effective text file size differs from the real one under MS-DOS */
  96.       if ((l = read(i, p, l)) < 1) {
  97.          (void)fprintf(stderr, "Tar: can\'t read \'%s\'\n", fname);
  98.          done(ERRARG);
  99.       }
  100.       (void)close(i);
  101.    } else if ((st.st_mode & S_IFMT) == S_IFCHR || /* character device */
  102.               (st.st_mode & S_IFMT) == S_IFIFO) { /* pipe */
  103.       int j, m; long s;
  104.  
  105.       for (s=0, m=INDMAX+1; m>=INDMIN; ) {
  106.          if ((p = malloc(m)) != NULL) goto ok;
  107.          m = ((m+INDLOW) & ~INDLOW) / 2;
  108.       }
  109.       outmem(stderr);
  110. ok:
  111.       s = 0;
  112.       do {
  113.          l = (int)s;
  114.          j = read(i, p+l, m-l);
  115.          s += j;
  116.       } while (j>0 && s<m);
  117.       if (j < 0) {
  118.          (void)fprintf(stderr, "Tar: error reading \'%s\'\n", fname);
  119.          done(ERRARG);
  120.       }
  121.       if (s >= m) {
  122.          if (m < INDMAX) {
  123.             outmem(stderr);
  124.          } else {
  125.             (void)fprintf(stderr,"Tar: \'%s\' exceeds limit in size\n",fname);
  126.             done(ERRARG);
  127.          }
  128.       }
  129.       if (l+1 < m) {
  130.          free(p);
  131.          if ((p = realloc(p, l+1)) == NULL) {
  132.             (void)fprintf(stderr, "Tar: error shrinking memory block\n");
  133.             done(ERRARG);
  134.          }
  135.       }
  136.    } else {
  137.       (void)fprintf(stderr, "Tar: \'%s\' not a file\n", fname);
  138.       done(ERRARG);
  139.    }
  140.    p[l] = '\0';
  141.    return buildarg(argc, argv, (*buf=p));
  142. }
  143.  
  144. int envbuild(argc, argv)
  145. char ***argv;
  146. {
  147.    register i;
  148.    register char *p;
  149.  
  150.    if ((p = getenv("TARCMD")) == NULL) return 0;
  151.    i = strlen(p); if (!i) return 0;
  152. #ifdef UNIX
  153. #  define ARGFILE
  154.    if (p[0] == '/')
  155. #endif
  156. #ifdef MSDOS
  157. #  define ARGFILE
  158.    if (((p[0] <= 'A' && p[0] >= 'Z') || (p[0] <= 'a' && p[0] >= 'z')) &&
  159.        p[1] == ':' && p[2] == '\\' || p[0]=='\\')
  160. #endif
  161. #ifdef ARGFILE
  162.    return argfile(argc, argv, p, &tarcmd);
  163. #endif
  164. #if 0 /*ndef MSDOS*/
  165.    /* Make a copy of environment variable to avoid protection problems */
  166.    tarcmd = salloc(i+1); (void)MEMCPY(tarcmd, p, i+1); p = tarcmd;
  167. #endif
  168.    return buildarg(argc, argv, p);
  169. }
  170.  
  171. /* ARGSUSED */ static void readblk(p, argv, i)
  172. char **p, **argv; int *i;
  173. {
  174.    register char *s;
  175.    register n;
  176.  
  177.    if (cblock) {
  178.       (void)fprintf(stderr, "Tar: blocksize multiply defined\n");
  179.       done(ERRARG);
  180.    }
  181.    s = argv[++*i];
  182.    for (cblock=0,n=0; digit(*s) && n<3; ++n,s++) cblock = *s-'0' + 10*cblock;
  183.    if (n>0 && n<=2) {
  184.       if      (*s == 'k' || *s == 'K') { cblock *= 2; s++; }
  185.       else if (*s == 'b' || *s == 'B') s++;
  186.       if (*s=='\0' && cblock>0 && cblock<=MAXBLOCK) /* blocksize ok */ return;
  187.    }
  188.    (void)fprintf(stderr, "Tar: bad blocksize (max is %d)\n", MAXBLOCK);
  189.    done(ERRARG);
  190. #ifdef __TURBOC__
  191.    (void)p;
  192. #endif
  193. }
  194.  
  195. #ifdef MSDOS
  196. static void readvol(p, argv, i)
  197. char **p, **argv; int *i;
  198. {
  199.    register char *s;
  200.    register n;
  201.  
  202.    if (k_flag || tapename) {
  203.       (void)fprintf(stderr, "Tar: tape device multiply defined\n");
  204.       done(ERRARG);
  205.    }
  206.    k_flag = TRUE;
  207.    s = argv[++*i];
  208.    for (volume=0, n=0; digit(*s) && n<7; ++n,s++) volume = *s-'0' + 10*volume;
  209.    if (n>0 && n<=6) {
  210.       if      (*s == 'm' || *s == 'M') { volume <<= 11; ++s; }
  211.       else if (*s == 'k' || *s == 'K') { volume += volume; ++s; }
  212.       else if (*s == 'b' || *s == 'B') ++s;
  213.       else volume += volume;
  214.       if ((volume & ~0x7FFE) == 0)
  215.          if (*s=='\0' && argdisk((int)volume >> 1) == 0)
  216.             /* diskette size ok */ return;
  217.    }
  218.    (void)fprintf(stderr, "Tar: Invalid diskette size\n");
  219.    done(ERRARG);
  220. #ifdef __TURBOC__
  221.    (void)p;
  222. #endif
  223. }
  224. #endif
  225.  
  226. /* ARGSUSED */ static void readpk(p, argv, i)
  227. char **p, **argv; int *i;
  228. {
  229.    register c;
  230.    c = (*p)[0]; if (c>='A' && c<='Z') c += 'z'-'Z';
  231.  
  232.    if (pktype != PKNONE) {
  233.       (void)fprintf(stderr,"Tar: compression method multiply defined\n");
  234.       done(ERRARG);
  235.    }
  236.    if (c == 'z' || c == ',') {
  237.       pktype = c==',' ? PKpLZW : PKfLZW;
  238.       lzwbits = BITS;
  239.       if ((*p)[1] == '9') {
  240.          *p += 1; lzwbits = 9;
  241.       } else if ((*p)[1] == '1') {
  242.          *p += 2; lzwbits = 10 + **p - '0';
  243.          if (lzwbits < 10 || lzwbits > BITS) {
  244.             (void)fprintf(stderr, "Tar: Invalid bits factor\n");
  245.             done(ERRARG);
  246.          }
  247.       }
  248.    } else {
  249.       pktype = c=='.' ? PKZIP : PKDEF;
  250.       ziplevel = 6; /* default */
  251.       if (digit((*p)[1])) {
  252.          *p += 1; ziplevel = **p - '0';
  253.       }
  254.    }
  255. #ifdef __TURBOC__
  256.    (void)argv; (void)i;
  257. #endif
  258. }
  259.  
  260. #ifdef MSDOS
  261. /* ARGSUSED */ static void devno(p, argv, i)
  262. char **p, **argv; int *i;
  263. {
  264.    ndrive = **p & 7; setdrive = TRUE;
  265. #ifdef __TURBOC__
  266.    (void)argv; (void)i;
  267. #endif
  268. }
  269. #endif
  270.  
  271. static void readxcl(p, argv, i)
  272. char **p, **argv; int *i;
  273. {
  274.    if (xcnt >= XMAX) {
  275.       (void)fprintf(stderr,"Tar: too many \'%s\'s\n", **p ? "#" : argv[*i]);
  276.       done(ERRARG);
  277.    }
  278.    xarg[xcnt++] = argv[++*i];
  279. }
  280.  
  281. #define TO_APP  '\377'
  282. #define TO_INC  '\376'
  283. #define TO_REM  '\375'
  284. #define TO_CALL '\374'
  285. #define MAXOPT  8
  286.  
  287. /* Number of compiles does not allow correct union initialization,
  288.    that's why I have to use this ugly nested structure. */
  289. static struct {
  290.    struct {
  291.       void (*fun) __ARGS__((char**, char**, int*));
  292.       char *x;
  293.    } p;
  294.    char longop[MAXOPT], shortop;
  295.    char optype, xflag;
  296. } oplist[] = {
  297.    {{NULL, &a_flag}, "append",   'a', TRUE,    0},
  298.    {{NULL, &a_flag}, "append",   'r', TRUE,    0},
  299.    {{NULL, &c_flag}, "create",   'c', TRUE,    0},
  300.    {{NULL, &x_flag}, "extract",  'x', TRUE,    0},
  301.    {{NULL, &t_flag}, "list",     't', TO_INC,  0},
  302.    {{NULL, &y_flag}, "move",     'y', TRUE,    0},
  303.    {{NULL, &u_flag}, "update",   'u', TRUE,    0},
  304.    {{NULL, &d_flag}, "delete",   'd', TRUE,    0},
  305.    {{NULL, &v_flag}, "verbose",  'v', TO_INC,  0},
  306.    {{NULL, &w_flag}, "interact", 'w', TRUE,    0},
  307.    {{NULL, &i_flag}, "inhibit",  'i', TRUE,    0},
  308.    {{NULL, &s_flag}, "strict",   's', TRUE,    0},
  309.    {{NULL, &m_flag}, "modifica", 'm', TRUE,    0},
  310.    {{NULL, &j_flag}, "comment",  'j', TRUE,    0},
  311.    {{NULL, &nonest}, "nonest",   'n', TRUE,    0},
  312.    {{NULL, &o_flag}, "",         'o', TRUE,    0},
  313. #ifdef UNIX
  314.    {{NULL, &dslash}, "",         '/', TRUE,    0},
  315.    {{NULL, &l_flag}, "link-war", 'l', TRUE,    0},
  316.    {{NULL, &p_flag}, "permissi", 'p', TRUE,    0},
  317.    {{NULL, &ndrive}, "",         '0', 0,       0},
  318.    {{NULL, &ndrive}, "",         '1', 1,       0},
  319.    {{NULL, &ndrive}, "",         '2', 2,       0},
  320.    {{NULL, &ndrive}, "",         '3', 3,       0},
  321.    {{NULL, &ndrive}, "",         '4', 4,       0},
  322.    {{NULL, &ndrive}, "",         '5', 5,       0},
  323.    {{NULL, &ndrive}, "",         '6', 6,       0},
  324.    {{NULL, &ndrive}, "",         '7', 7,       0},
  325. #endif
  326. #ifdef MSDOS
  327.    {{NULL, &dslash}, "",         '\\',TRUE,    0},
  328.    {{NULL, &l_flag}, "link-cop", 'l', TRUE,    0},
  329.    {{readvol, NULL}, "",         'k', TO_CALL, 0},
  330.    {{NULL, &deldrv}, "",         ':', TRUE,    0},
  331.    {{devno, NULL},   "",         '0', TO_CALL, 0},
  332.    {{devno, NULL},   "",         '1', TO_CALL, 0},
  333.    {{devno, NULL},   "",         '2', TO_CALL, 0},
  334.    {{devno, NULL},   "",         '3', TO_CALL, 0},
  335. #endif
  336.    {{NULL, (char*)&tapename}, "file", 'f', TO_REM,  0},
  337.    {{readblk, NULL}, "block-si", 'b', TO_CALL, 0},
  338.    {{NULL, NULL},    "",         '@', TO_APP,  0},
  339.    {{readxcl, NULL}, "exclude",  '#', TO_CALL, 0},
  340.    {{readpk, NULL},  "",         ',', TO_CALL, 0},
  341.    {{readpk, NULL},  "",         '.', TO_CALL, 0},
  342.    {{readpk, NULL},  "",         'e', TO_CALL, 0},
  343.    {{readpk, NULL},  "",         'z', TO_CALL, 0},
  344.    {{NULL, &pktype}, "compress",  0,  PKpLZW,  0},
  345.    {{NULL, &pktype}, "zip-arch",  0,  PKZIP,   0},
  346.    {{NULL, &pktype}, "zip-file",  0,  PKDEF,   0},
  347.    {{NULL, &gnuzip}, "gzip",      0,  TRUE,    0},
  348.    {{NULL, &gnuzip}, "gnu",       0,  TRUE,    0},
  349. };
  350.  
  351. void cleanopt()
  352. {
  353.    register i;
  354.    for (i=0; i<dimof(oplist); i++) {
  355.       switch (oplist[i].optype) {
  356.          case TO_REM:  *(char**)(oplist[i].p.x) = NULL;
  357.          case TO_CALL: break;
  358.          default:      *(oplist[i].p.x) = 0;
  359.       }
  360.       oplist[i].xflag = 0;
  361.    }
  362. }
  363.  
  364. static void cmpflags __ARGS__((char**, int, int));
  365.  
  366. static void cmpflags(fl, n, to_break)
  367. char *fl[];
  368. {
  369.    register i;
  370.    register x0, x1;
  371.  
  372.    for (x0=x1=0, i=0; i<n; i++) {
  373.       if (*(fl[i])) { if (*(fl[i]) & OPTFLAG) ++x1; else ++x0; }
  374.    }
  375.    if (x0 == 1) {
  376.       for (i=0; i<n; i++) if (*(fl[i]) & OPTFLAG) *(fl[i]) = 0;
  377.    } else if (x0>1 || x1>1) {
  378.       (void)fprintf(stderr, "Tar: ambiguous options\n");
  379.       if (to_break) done(ERRARG);
  380.    }
  381. }
  382.  
  383. int readopt(argc, argv, aux)
  384. int *argc; char ***argv;
  385. {
  386.    register c;
  387.    register j, k;
  388.    char lex[MAXOPT];
  389.    char *p;
  390.    int i;
  391.    char *fl[5];
  392.  
  393.    if (*argc < 1) {
  394.       (void)fprintf(stderr, "Tar: no options to read\n");
  395.       done(ERRARG);
  396.    }
  397.    for (i=0; i<*argc; i++) {
  398.       p = (*argv)[i];
  399.       if (switchar(*p)) {
  400.          if (p[1] == '\0') goto end;
  401.          if (p[1] != '-' || p[0] != '-') ++p;
  402.       } else if (*p != '+' && i) goto end;
  403.  
  404.       if (p[0]!='+' && (p[0]!='-' || p[1]!='-')) {
  405.          for (;*p; p++) {
  406.             c = *p; if (switchar(c)) goto end;
  407.             if (c>='A' && c<='Z') c += 'z'-'Z';
  408.             for (k=0; k<dimof(oplist); k++) {
  409.                if (c == oplist[k].shortop) goto sfound;
  410.             }
  411.             (void)fprintf(stderr, "Tar: bad option \'%c\'\n", *p);
  412.             done(ERRARG);
  413. sfound:     switch (oplist[k].optype) {
  414.                case TO_APP:
  415.                   if (aux) {
  416.                      appname = (*argv)[++i];
  417.                   } else {
  418.                      *argc = argfile(*argc, argv, (*argv)[++i], &responce);
  419.                   }
  420.                   break;
  421.                case TO_REM:
  422.                   if (*(oplist[k].p.x) && oplist[k].xflag == aux) {
  423.                      (void)fprintf(stderr,"Tar: duplicate \'%c\'\n",*p);
  424.                      done(ERRARG);
  425.                   }
  426.                   *(char**)(oplist[k].p.x) = (*argv)[++i];
  427.                   break;
  428.                case TO_CALL:
  429.                   (*(oplist[k].p.fun))(&p, (*argv), &i);
  430.                   break;
  431.                case TO_INC:
  432.                   if (oplist[k].xflag != aux) *(oplist[k].p.x) = 0;
  433.                   *(oplist[k].p.x) = aux | (1 + *(oplist[k].p.x));
  434.                   break;
  435.                default:
  436.                   if (*(oplist[i].p.x) && oplist[k].xflag == aux) {
  437.                      (void)fprintf(stderr,"Tar: duplicate \'%c\'\n",*p);
  438.                      done(ERRARG);
  439.                   }
  440.                   *(oplist[k].p.x) = aux | oplist[k].optype;
  441.             }
  442.             oplist[k].xflag = aux;
  443.          }
  444.       } else {
  445.          if (p[0] == '+') p += 1; else p += 2;
  446.          for (j=0; *p; p++) {
  447.             if (j < MAXOPT) {
  448.                c = *p; if (c>='A' && c<='Z') c += 'z'-'Z';
  449.                lex[j++] = c;
  450.             }
  451.          }
  452.          if (!j) goto end;
  453.          for (k=0; k<dimof(oplist); k++) {
  454.             if (oplist[k].longop[0] &&
  455.                 0 == strncmp(oplist[k].longop, lex, j)) goto lfound;
  456.          }
  457.          (void)fprintf(stderr, "Tar: bad option \'%s\'\n", (*argv)[i]);
  458.          done(ERRARG);
  459. lfound:  switch (oplist[k].optype) {
  460.             case TO_APP:
  461.                if (aux) {
  462.                   appname = (*argv)[++i];
  463.                } else {
  464.                   *argc = argfile(*argc, argv, (*argv)[++i], &responce);
  465.                }
  466.                break;
  467.             case TO_REM:
  468.                if (*(oplist[k].p.x) && oplist[k].xflag == aux) {
  469.                   (void)fprintf(stderr, "Tar: duplicate \'%s\'\n", (*argv)[i]);
  470.                   done(ERRARG);
  471.                }
  472.                *(char**)(oplist[k].p.x) = (*argv)[++i];
  473.                break;
  474.             case TO_CALL:
  475.                (*(oplist[k].p.fun))(&p, (*argv), &i);
  476.                break;
  477.             case TO_INC:
  478.                if (oplist[k].xflag != aux) *(oplist[k].p.x) = 0;
  479.                *(oplist[k].p.x) = aux | (1 + *(oplist[k].p.x));
  480.                break;
  481.             default:
  482.                if (*(oplist[k].p.x) && oplist[k].xflag == aux) {
  483.                   (void)fprintf(stderr,
  484.                      "Tar: duplicate \'%s\'\n", (*argv)[i]);
  485.                   done(ERRARG);
  486.                }
  487.                *(oplist[k].p.x) = oplist[k].optype;
  488.          }
  489.          oplist[k].xflag = aux;
  490.       }
  491.    }
  492. end:
  493.    fl[0] = &c_flag; fl[1] = &u_flag;                  cmpflags(fl, 2, TRUE);
  494.    fl[0] = &a_flag; fl[1] = &x_flag; fl[2] = &t_flag; cmpflags(fl, 3, TRUE);
  495.    fl[0] = &d_flag; fl[3] = &c_flag;                  cmpflags(fl, 4, TRUE);
  496.    fl[0] = &d_flag; fl[1] = &i_flag;                  cmpflags(fl, 2, TRUE);
  497.    if (c_flag && !a_flag)            a_flag = c_flag;
  498.    if (u_flag && !a_flag && !x_flag) a_flag = u_flag;
  499.    if (a_flag && !c_flag) {
  500.       fl[0] = &a_flag; fl[1] = &i_flag;               cmpflags(fl, 2, TRUE);
  501.    }
  502.    fl[0] = &u_flag; fl[1] = &m_flag;                  cmpflags(fl, 2, FALSE);
  503.    return i;
  504. }
  505.